package org.springblade.modules.admin.controller.feishu;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.google.common.collect.Lists;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.springblade.common.enums.FeiShuDocumentEnum;
import org.springblade.common.utils.CookieUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.admin.dto.feishu.FeiShuBatchDTO;
import org.springblade.modules.admin.dto.feishu.FeiShuCreateBatchDTO;
import org.springblade.modules.admin.dto.feishu.FeiShuFieldsDTO;
import org.springblade.modules.admin.entity.CompanyElevatorTrack;
import org.springblade.modules.admin.service.ICompanyElevatorTrackService;
import org.springblade.modules.admin.service.feishu.IFeiShuDocumentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: Sharry
 * @createTime: 2024-01-30 17:25
 * @version: Version-1.0
 */
@RestController
@RequestMapping("/admin/maintain/spider/feishu")
@Api(value = "/admin/maintain/spider/feishu", tags = "飞书维保爬虫控制器")
@Slf4j
public class FeiShuMaintainSpiderController {

	@Autowired
	private ICompanyElevatorTrackService companyElevatorTrackService;

	@Autowired
	private IFeiShuDocumentService feiShuDocumentService;

	@GetMapping("/company/maintain")
	public void companyMaintain() {
		// 开始时间
		long start = System.currentTimeMillis();
		// 获取一次cookie
		String cookie = CookieUtil.getCookie();
		// Jsoup 解析网页
		Document doc = null;
		try {
			doc = Jsoup
				.connect("http://wsbj2.gdsei.org.cn:8078/seimis/wbglAction.do?method=wbsh&ec_i=ec&eti=&eti_p=&ec_efn=&ec_ev=&ec_crd=1000&ec_f_a=&ec_p=1&ec_s_USERORGNAME=&ec_s_SYORGANCODE=&ec_s_PARTICULARADDR=&ec_s_PROORGNAME=&ec_s_WBORGANCODE=&ec_s_WBHTBH=&ec_s_STATE=&task=view&SYSFUNCODE=QYPT_SBGL_WBSQCX&method=wbsh&checkflag=1&ec_totalpages=0&ec_totalrows=&ec_f_radio=&ec_f_%E5%BA%8F%E5%8F%B7=&ec_f_%E6%93%8D%E4%BD%9C=&ec_f_USERORGNAME=&ec_f_SYORGANCODE=&ec_f_PARTICULARADDR=&ec_f_PROORGNAME=&ec_f_WBORGANCODE=&ec_f_WBHTBH=&ec_f_STATE=&ec_pg=1&ec_rd=1000&SYDWNAME=&WBDWNAME=&HTBH=&1706587461633")
				.cookie("Cookie", cookie)
				.get();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		/**
		 * <tr class="even "  onclick="ECSideUtil.selectRow(this,'ec');"  onmouseover="ECSideUtil.lightRow(this,'ec');"  onmouseout="ECSideUtil.unlightRow(this,'ec');"   >
		 *     <td width="15"   >
		 * 	    	<input type="checkbox" name="a_ID" value="02da94a3-ce00-47b5-a36c-e9a1373d7dfa" style="border:0px;"/>
		 * 	   </td>
		 *     <td width="30"   >6</td>
		 *     <td nowrap="true"   >
		 * 	       <input type="button" name="edit" value="详细" onclick="do_edit('02da94a3-ce00-47b5-a36c-e9a1373d7dfa')" style="width:24" class="button_cd2">
		 * 	    </td>
		 * <td  >中山市沙溪镇港园村股份合作经济联合社</td>
		 * <td  >789493833</td>
		 * <td  >广东省中山市沙溪镇港园村下大街６号</td>
		 * <td  >中山市银河机电设备有限公司</td>
		 * <td  >568274135</td>
		 * <td  >IMC2016-1085/2017</td>
		 * <td  >审核已通过</td>
		 * </tr>
		 */
		// 获取以上格式格式的onclick="do_edit('02da94a3-ce00-47b5-a36c-e9a1373d7dfa')"里的do_edit的参数以及最后一个td审核的值
		List<Map<String, String>> mapList = new ArrayList<>();
		doc.select("tr[onclick^=ECSideUtil.selectRow]").forEach(element -> {
			Elements tds = element.select("td");
			// <input type="button" name="edit" value="详细" onclick="do_edit('02da94a3-ce00-47b5-a36c-e9a1373d7dfa')" style="width:24" class="button_cd2>"
			// 获取所有这样的格式的onclick="do_edit('02da94a3-ce00-47b5-a36c-e9a1373d7dfa')"里的do_edit的参数
			String id = tds.get(2).select("input").attr("onclick");
			id = id.substring(id.indexOf("'") + 1, id.lastIndexOf("'"));
			String reviewStatus = tds.get(9).text();
			Map<String, String> map = new HashMap<>();
			map.put("id", id);
			map.put("reviewStatus", reviewStatus);
			mapList.add(map);
		});
		log.info("========共分 " + (mapList.size() / 100 + 1) + "组执行=======");
		// 将ids 每100个分成一组
		List<List<Map<String, String>>> partition = Lists.partition(mapList, 100);
		int count = 0;
		List<CompanyElevatorTrack> targetList = new ArrayList<>();
		// 遍历每一组
		for (List<Map<String, String>> idMapList : partition) {
			for (Map<String, String> idMap : idMapList) {
				String id = idMap.get("id");
				String reviewStatus = idMap.get("reviewStatus");
				Document doc1 = null;
				try {
					doc1 = Jsoup
						.connect("http://wsbj2.gdsei.org.cn:8078/seimis/wbglAction.do?method=wbsh_edit&task=view&WBSQSYSID=" + id)
						.cookie("Cookie", cookie)
						.timeout(60000)
						.get();
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
				// <input type="text" name="SYDWNAME" value="中山市信泓实业有限公司" readonly="readonly" id="SYDWNAME" style="width:250px">
				// 获取value 里的字段
				String companyName = doc1.select("input[name=SYDWNAME]").attr("value");
				//<input type="text" name="HTBH" value="WB2019-0613/MNT2019" readonly="readonly" style="width:170px" alt="1">
				// 获取value 里的字段
				String maintainContractNum = doc1.select("input[name=HTBH]").attr("value");
				// <input type="text" name="EXPDATE" value="2020-06-10" style="width:70%">
				// 获取value 里的字段
				String effectiveTime = doc1.select("input[name=EXPDATE]").attr("value");
				// 获取上述所有这样格式的 td, id的属性值为tr001
				Elements elements = doc1.select("tr[id^=tr]");
				// 获取所有的td
				elements.forEach(element -> {
					// 获取每个td里的所有内容
					String text = element.text();
					System.out.println(text);
					// 按逻辑分割，如果内容里也是空格，那么就算该空格也是一个值
					String[] split = StrUtil.split(text, " ").toArray(new String[0]);
					// 当长度有这么长时，再进行下一步操作
					// 获取第一个元素, 先判断下标是否越界，是：插入，否：不插入
					String deviceType = "/";
					String deviceCode = "/";
					String usePermitNum = "/";
					String companyNum = "/";
					String privateNum = "/";
					CompanyElevatorTrack companyElevatorTrack = new CompanyElevatorTrack();
					if (split.length != 6) {
						companyElevatorTrack.setIsNormal(1);
					}
					// 第一个元素为序号，忽略。直接获取第二个元素
					if (1 <= split.length - 1) {
						deviceType = Func.isBlank(split[1]) ? "/" : split[1];
					}
					// 获取第三个元素
					if (2 <= split.length - 1) {
						deviceCode = Func.isBlank(split[2]) ? "/" : split[2];
					}
					// 获取第四个元素
					if (3 <= split.length - 1) {
						usePermitNum = Func.isBlank(split[3]) ? "/" : split[3];
					}
					// 获取第五个元素
					if (4 <= split.length - 1) {
						companyNum = Func.isBlank(split[4]) ? "/" : split[4];
					}
					// 获取第六个元素
					if (5 <= split.length - 1) {
						privateNum = Func.isBlank(split[5]) ? "/" : split[5];
					}
					companyElevatorTrack.setCompanyName(companyName);
					companyElevatorTrack.setMaintainContractNum(maintainContractNum);
					companyElevatorTrack.setEffectiveTime(effectiveTime);
					companyElevatorTrack.setDeviceType(deviceType);
					companyElevatorTrack.setDeviceCode(deviceCode);
					companyElevatorTrack.setUsePermitNum(usePermitNum);
					companyElevatorTrack.setCompanyNum(companyNum);
					companyElevatorTrack.setPrivateNum(privateNum);
					companyElevatorTrack.setReviewStatus(reviewStatus);
					targetList.add(companyElevatorTrack);
				});
			}
			try {
				count++;
				log.info("========第" + count + "组执行完毕，休息2秒=======");
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				throw new RuntimeException(e);
			}
		}
		// 批量插入
		companyElevatorTrackService.saveBatch(targetList);
		// 结束时间
		long end = System.currentTimeMillis();
		// 耗时
		long time = end - start;
		log.info("========爬取完毕共耗时{}秒=======", time / 1000);
	}

	@GetMapping("/company/maintain/feishu")
	public void companyMaintainFeiShu() {
		// 0. 更新流程：先列出全部记录，获取当前全部record_id 集合。现阶段先删除后新增，则完成更新
		String result = "";
		// 1. 数据准备：目标文件夹Token、文档ID; 需要更新的数据列表
		// 1.1 目标文件夹Token、文档ID
		String appToken = FeiShuDocumentEnum.GOVERNMENT_ELEVATOR_TRACK_COPY.getAppToken();
		String tableId = FeiShuDocumentEnum.GOVERNMENT_ELEVATOR_TRACK_COPY.getTableId();

		// 1.2 需要更新的数据列表
		List<CompanyElevatorTrack> updateTargetList = companyElevatorTrackService.list(
			new LambdaQueryWrapper<CompanyElevatorTrack>()
				.eq(CompanyElevatorTrack::getReviewStatus, "审核已通过")
		);
		// updateTargetList 过滤： 根据 deviceCode 分组，effectiveTime 最大的一条 effective_time 格式为 String"2021-11-16" 格式，转换为时间戳比较
		Map<String, CompanyElevatorTrack> collect = updateTargetList
			.stream()
			.collect(
				Collectors.groupingBy(CompanyElevatorTrack::getDeviceCode,
					Collectors.collectingAndThen(
						Collectors.maxBy(Comparator.comparing(c -> DateUtil.parse(c.getEffectiveTime()).getTime())),
						Optional::get
					)
				)
			);
		updateTargetList = new ArrayList<>(collect.values());

		// 2. 数据封装
		FeiShuCreateBatchDTO feiShuCreateBatchDTO = new FeiShuCreateBatchDTO();
		List<FeiShuFieldsDTO> records = new ArrayList<>();
		for (CompanyElevatorTrack c : updateTargetList) {
			FeiShuFieldsDTO element = new FeiShuFieldsDTO();
			Map<String, Object> elementMap = new HashMap<>(10);
			elementMap.put("设备注册代码", c.getDeviceCode());
			elementMap.put("使用单位名称", c.getCompanyName());
			elementMap.put("维保合同编号", c.getMaintainContractNum());
			elementMap.put("出厂编号", c.getCompanyNum());
			elementMap.put("使用证编号", c.getUsePermitNum());
			elementMap.put("维保有效期", c.getEffectiveTime());
			elementMap.put("单位内编号", c.getPrivateNum());
			elementMap.put("是否存在爬取数据错漏的风险（仅供参考）",
				new Integer("1").equals(c.getIsNormal()) ? "是" : "否");
			element.setFields(elementMap);
			records.add(element);
		}
		// records 去重
		Set<FeiShuFieldsDTO> set = new HashSet<>(records);
		// 清空 records, 将 set 中的数据添加到 records 中
		records.clear();
		records.addAll(set);
		feiShuCreateBatchDTO.setRecords(records);
		// 全量删除再覆盖
		List<JSONObject> jsonObjects = feiShuDocumentService.commandQueryBatch(appToken, tableId, null);
		// 遍历并获取 jsonObjects 的 封装成 FeiShuBatchDTO 对象
		List<String> r = new ArrayList<>();
		jsonObjects.forEach(j -> r.add(j.getString("record_id")));
		FeiShuBatchDTO deleteFeiShuBatchDTO = new FeiShuBatchDTO();
		deleteFeiShuBatchDTO.setRecords(r);
		// 删除
		feiShuDocumentService.commandDeleteBatchLimit(appToken, tableId, deleteFeiShuBatchDTO);
		// 新增
		result = feiShuDocumentService.commandAddBatchLimit(appToken, tableId, feiShuCreateBatchDTO);
		// 5. 发送消息, 通知到群
		List<JSONObject> targetGroupObjects = feiShuDocumentService.commandQueryGroupsBatch();
		List<String> chatIds = new ArrayList<>();
		targetGroupObjects.forEach(t -> chatIds.add(t.getString("chat_id")));
		// 发送消息
		String finalResult = result;
		chatIds.forEach(c -> {
			// 组装数据
			JSONObject bodyJson = new JSONObject();
			bodyJson.put("receive_id", c);
			bodyJson.put("msg_type", "text");
			HashMap<String, String> contentMap = new HashMap<>(2);
			String message = "覆盖"+FeiShuDocumentEnum.getDescription(appToken,tableId)+"结果：" + finalResult;
			contentMap.put("text", message);
			// 将 contentMap 转换成 JSON 格式
			bodyJson.put("content", JSON.toJSONString(contentMap));
			feiShuDocumentService.commandSendGroupMessage(bodyJson.toJSONString());
		});
	}


}
